
use async_channel::{bounded as async_bounded, Sender as AsyncSender, Receiver as AsyncReceiver, TryRecvError as AsyncTryRecvError};
use crossbeam_channel::{bounded, Sender, Receiver, TrySendError, TryRecvError};
use crate::data_frame::DataInstance;
use crate::conf_init::{EVENT_FLOW_NORMAL_CONFINSTNCE};
use crate::indicators::IndicatorsMode;

pub mod dyn_runtime;

#[derive(Clone,Debug)]
pub struct AsyncRecvData {
    name: String,
    recv: AsyncReceiver<DataInstance>,
}

#[derive(Clone,Debug)]
pub struct AsyncSendData {
    name: String,
    send: AsyncSender<DataInstance>,
}

impl AsyncSendData {
    pub async fn send(&self, data: DataInstance){
        match self.send.send(data).await{
            Ok(_) => {},
            Err(e) => {
                error!("AsyncMPMCSend send failed [{}] [{:?}]", self.name, e);
                std::process::exit(-1);
            }
        }
    }
}

impl AsyncRecvData {
    pub async fn recv(&self)->Option<DataInstance>{
        match self.recv.recv().await{
            Ok(t) => {Some(t)},
            Err(e) => {
                error!("AsyncMPMCRecv recv failed [{}] [{:?}]", self.name, e);
                std::process::exit(-1);
            },
        }
    }
    pub async fn try_recv(&self)->Option<DataInstance>{
        match self.recv.try_recv(){
            Ok(t) => {Some(t)},
            Err(e) => {
                match e{
                    AsyncTryRecvError::Empty => {None},
                    AsyncTryRecvError::Closed => {
                        error!("AsyncMPMCRecv try_recv failed [{}] [{:?}]", self.name, e);
                        std::process::exit(-1);
                    },
                }
            },
        }
    }
    pub async fn len(&self)->usize{
        self.recv.len()
    }
}

pub fn async_data_channel_new(name: String) ->(AsyncSendData, AsyncRecvData){
    let (s,r) = async_bounded(EVENT_FLOW_NORMAL_CONFINSTNCE.node.async_channel_size);
    return (AsyncSendData {send: s, name: name.clone()}, AsyncRecvData {recv: r, name: name});
}

pub fn async_channel_new<T>() ->(AsyncSend<T>, AsyncRecv<T>){
    let (s,r) = async_bounded(EVENT_FLOW_NORMAL_CONFINSTNCE.node.async_channel_size);
    return (AsyncSend {send: s}, AsyncRecv {recv: r});
}

pub fn channel_new<T>() -> (SyncSender<T>, SyncRecv<T>){
    let (s,r) = bounded(EVENT_FLOW_NORMAL_CONFINSTNCE.node.sync_channel_size);

    return (SyncSender{send: s}, SyncRecv{recv: r});
}

pub fn channel_new_custom<T>(size: usize) -> (SyncSender<T>, SyncRecv<T>){
    let (s,r) = bounded(size);

    return (SyncSender{send: s}, SyncRecv{recv: r});
}

#[derive(Debug)]
pub struct SyncSender<T>{
    send: Sender<T>,
}
impl <T> SyncSender<T>{
    pub fn send(&self, data: T){
        match self.send.send(data){
            Ok(_) => {},
            Err(e) => {
                error!("SyncRecv send err {:?}", e);
                std::process::exit(-1);
            },
        }
    }
    pub fn try_send(&self, data: T)->Option<T>{
        match self.send.try_send(data){
            Ok(_) => {return None;},
            Err(e) => {
                match e{
                    TrySendError::Disconnected(_) =>{
                        error!("SyncSender try_send err Disconnected");
                        std::process::exit(-1);
                    },
                    TrySendError::Full(d) =>{return Some(d);},
                }
            },
        }
    }
}
#[derive(Debug,Clone)]
pub struct SyncRecv<T>{
    recv: Receiver<T>,
}
impl <T> SyncRecv<T>{
    pub fn recv(&self)->T{
        match self.recv.recv(){
            Ok(t) => {t},
            Err(e) => {
                error!("SyncRecv recv err {:?}", e);
                std::process::exit(-1);
            },
        }
    }
    pub fn try_recv(&self)->Option<T>{
        match self.recv.try_recv(){
            Ok(t) => {return Some(t);},
            Err(e) => {
                match e{
                    TryRecvError::Empty => {return None;},
                    TryRecvError::Disconnected => {
                        error!("SyncRecv try_recv Disconnected");
                        std::process::exit(-1);
                    },
                }
            },
        }
    }
}

#[derive(Debug,Clone)]
pub struct AsyncSend<T>{
    send: AsyncSender<T>,
}
impl <T> AsyncSend<T>{
    pub async fn send(&self, data: T){
        match self.send.send(data).await{
            Ok(_) => {},
            Err(e) => {
                error!("AsyncSend send err {:?}", e);
                std::process::exit(-1);
            },
        }
    }
}

#[derive(Debug,Clone)]
pub struct AsyncRecv<T>{
    recv: AsyncReceiver<T>,
}
impl <T> AsyncRecv<T>{
    pub async fn recv(&self)->T{
        match self.recv.recv().await{
            Ok(t) => {t},
            Err(e) => {
                error!("AsyncRecv recv err {:?}", e);
                std::process::exit(-1);
            }
        }
    }
}

#[derive(Deserialize)]
pub enum Level{
    Error,
    Warn,
    Info,
    Debug,
    Trace,
}

#[derive(Deserialize)]
pub struct ModeLogConf{
    mode: IndicatorsMode,
    node_level: Vec<NodeLogConf>,
}

#[derive(Deserialize)]
pub struct NodeLogConf{
    node: String,
    level: Level,
}
